package com.huangjue.backend.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.huangjue.backend.constant.RoleTypes;
import com.huangjue.backend.dto.ConversationRequest;
import com.huangjue.backend.dto.aiChatClient.AiRequestMessage;
import com.huangjue.backend.dto.aiChatClient.ClientRequest;
import com.huangjue.backend.entity.AiProgrammingConversation;
import com.huangjue.backend.entity.StudentCourse;
import com.huangjue.backend.entity.HomeworkFinished;
import com.huangjue.backend.prompt.BuildPrompt;
import com.huangjue.backend.prompt.impl.BuildPromptImpl;
import com.huangjue.backend.service.HomeworkFinishedService;
import com.huangjue.backend.mapper.HomeworkMapper;
import com.huangjue.backend.entity.Homework;
import com.huangjue.backend.mapper.AiProgrammingConversationMapper;
import com.huangjue.backend.service.AiConversationService;
import com.huangjue.backend.service.StudentCourseService;

import com.huangjue.backend.utils.ClientRequestBuilder;
import com.huangjue.backend.utils.HttpHeaderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.time.LocalDateTime;
import java.util.stream.Collectors;
import java.nio.charset.StandardCharsets;

@Service
public class AiConversationServiceImpl implements AiConversationService {

    private final ObjectMapper objectMapper = new ObjectMapper();
    @Autowired
    private WebClient webClient; // 直接使用已配置的Bean
    @Autowired
    private AiProgrammingConversationMapper AiProgrammingConversationMapper;
    @Autowired
    private StudentCourseService studentCourseService;
    @Autowired
    private HomeworkFinishedService homeworkFinishedService;
    @Autowired
    private HomeworkMapper homeworkMapper;

    @Value("${llm.model}")
    private String llmModel;
    @Value("${llm.apiUrl}")
    private String llmApiUrl;
    @Value("${llm.apiKey}")
    private String llmApiKey;

//    String defaultRoleType= "你是黄桷兰综合使用平台的助教，由黄桷兰提供的人工智能助手，你更擅长中文的对话和编程指导。你主要回答用户和编程相关的问题，且对于其涉及到的知识点用最基础的方式去讲解，确保一名初学者能够接受。黄桷兰 为专有名词，不可翻译成其他语言。";
//    String defaultConstrains="你会为用户提供安全，有帮助，准确的回答。同时，你会拒绝一切涉及恐怖主义，种族歧视，黄色暴力等问题的回答。";
    @Value("${ai.conversation.default.prompt.role}")
    private String defaultRoleType;
    @Value("${ai.conversation.default.prompt.constrains}")
    private String defaultConstrains;

    @Override
    public Flux<String> Conversation(ConversationRequest conversationRequest) {
        HttpHeaders headers = HttpHeaderUtil.createJsonBearerHeaders(llmApiKey);
        // 用于收集完整响应
        AtomicReference<StringBuilder> fullContent = new AtomicReference<>(new StringBuilder());
        //用于存储全部的请求信息
        List<AiRequestMessage> aiRequestMessages = new ArrayList<>();
        //获取文件内容
        if (conversationRequest.getFileUrl() != null
                && !"-1".equals(conversationRequest.getFileUrl())
                && !conversationRequest.getFileUrl().isEmpty()) {
            try {
                String fileUrl = conversationRequest.getFileUrl();
                int lastIndex = fileUrl.lastIndexOf("/");
                String fileName = lastIndex != -1 ? fileUrl.substring(lastIndex + 1) : fileUrl;
                String filePath = System.getProperty("user.dir") + "/uploads/homework/" + fileName;
                String content = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);

                AiRequestMessage fileMessage = new AiRequestMessage(RoleTypes.SYSTEM,content);//将文件内容放入请求消息
                aiRequestMessages.add(fileMessage);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        int roundNumber = getCurrentRoundNumber(
                conversationRequest.getUserId(),
                conversationRequest.getHomeworkId());
        // 获取用户最近10条对话记录
        List<AiProgrammingConversation> latestConversations = AiProgrammingConversationMapper
                .selectLatestConversations(conversationRequest.getUserId(),
                        conversationRequest.getHomeworkId(),5);

        for (AiProgrammingConversation conversation : latestConversations) {
            String userMessage = conversation.getUserMessage();
            String aiResponse = conversation.getAiResponse();

            //过滤掉以 "1\n[文件链接]：" 开头的 userMessage
            if (userMessage != null && userMessage.startsWith("1\n[文件链接]：")) {
                continue;
            }

            // 预处理并检查有效性
            boolean isValidUserMessage = userMessage != null && !userMessage.trim().isEmpty();
            boolean isValidAiResponse = aiResponse != null && !aiResponse.trim().isEmpty();

            if (isValidUserMessage && isValidAiResponse) {
                aiRequestMessages.add(new AiRequestMessage(RoleTypes.USER,aiResponse));
                aiRequestMessages.add(new AiRequestMessage(RoleTypes.ASSISTANT,aiResponse));
            }
        }

        BuildPrompt promptBuilder = new BuildPromptImpl()
                .role(defaultRoleType)
                .constrains(defaultConstrains);

        String systemPrompt = promptBuilder.buildSystemPrompt();
        ClientRequestBuilder builder = new ClientRequestBuilder()
                .model(llmModel)
                .system(systemPrompt)
                .user(conversationRequest.getContent())
                .temperature(0.1)
                .stream(true);

        if (aiRequestMessages != null && !aiRequestMessages.isEmpty()) {
            /*
            todo
            *当历史消息过长后，对话无法正确识别用户意图，故不采用多轮对话
             */
//            builder.addAll(aiRequestMessages);
        }

        ClientRequest req = builder.build();
        System.out.println(req);
        return webClient.post()
                .uri(llmApiUrl)
                .headers(httpHeaders -> httpHeaders.addAll(headers))
                .bodyValue(req)
                .retrieve()
                .bodyToFlux(String.class)
//                .doOnNext(line -> System.out.println("原始响应: " + line))
                .filter(line -> !line.trim().isEmpty() && !line.trim().equals("[DONE]"))
                .doOnError(WebClientResponseException.class, ex -> {
                    // 处理WebClient响应异常
                    System.err.println("WebClient Error - Status: " + ex.getStatusCode() +
                            ", Message: " + ex.getResponseBodyAsString());
                })
                .flatMap(json -> {
                    try {
                        Map<String, Object> response = objectMapper.readValue(json, Map.class);
                        List<Map<String, Object>> choices = (List<Map<String, Object>>) response.get("choices");

                        if (choices != null && !choices.isEmpty()) {
                            Map<String, Object> choice = choices.get(0);
                            Map<String, Object> delta = (Map<String, Object>) choice.get("delta");

                            // 处理首次响应（包含角色信息）
                            if (delta != null) {
                                String content = (String) delta.get("content");
                                // 返回有效内容
                                if (content != null) {
//                                    System.out.println("返回响应：" + content);
                                    fullContent.get().append(content);
                                    return Mono.just(content);
                                }
                                // 处理角色信息（首次响应）
                                else if (delta.get("role") != null) {
//                                    System.out.println("忽略角色信息");
                                    return Mono.just("");
                                }
                            }
                        }
//                        System.out.println("返回空响应");
                        return Mono.just("");
                    } catch (Exception e) {
//                        System.err.println("JSON解析错误: " + json);
                        return Mono.just("[解析错误]");
                    }
                })
                .doOnComplete(() -> {
                    // 流结束时处理完整内容
                    String completeResponse = fullContent.get().toString();
                    System.out.println("完整响应内容: " + completeResponse);
                    // 这里可以保存完整响应到数据库
                    AiProgrammingConversation  aiProgrammingConversation = new AiProgrammingConversation();
                    aiProgrammingConversation.setUserId(conversationRequest.getUserId());
                    aiProgrammingConversation.setHomeworkId(conversationRequest.getHomeworkId());
                    if (conversationRequest.getFileUrl() != null && !conversationRequest.getFileUrl().isEmpty()) {
                        aiProgrammingConversation.setUserMessage("1\n[文件链接]：" + conversationRequest.getFileUrl());
                    } else {
                        aiProgrammingConversation.setUserMessage(conversationRequest.getContent());
                    }
                    aiProgrammingConversation.setAiResponse(completeResponse);
                    aiProgrammingConversation.setRoundNumber(roundNumber);
                    AiProgrammingConversationMapper.insertConversation(aiProgrammingConversation);

                    //更新学生课程表中的demonum
                    Integer userId = Integer.valueOf(conversationRequest.getUserId());
                    Integer courseId = Integer.valueOf(conversationRequest.getCourseId());
                    System.out.println("userId = " + userId + ", courseId = " + courseId);
                    StudentCourse sc = studentCourseService.getByUserIdAndCourseId(userId, courseId);
                    System.out.println("查到的StudentCourse: " + sc);
                    if (sc != null) {
                        System.out.println("demoNum = " + sc.getDemoNum() + ", demoUnlock = " + sc.getDemoUnlock());
                    }
                    // 1. 添加homework_finished记录
                    HomeworkFinished finished = new HomeworkFinished();
                    finished.setUserId(userId);
                    finished.setHomeworkId(Integer.valueOf(conversationRequest.getHomeworkId()));
                    finished.setIsFinished(1);
                    finished.setFinishTime(LocalDateTime.now());
                    homeworkFinishedService.insert(finished);

                    // 2. 检查该demo下所有作业是否完成
                    // 2.1 获取当前作业的demoId
                    Homework currentHomework = homeworkMapper.selectById(Integer.valueOf(conversationRequest.getHomeworkId()));
                    Integer demoId = currentHomework.getDemoId();
                    // 2.2 获取该demo下所有作业id
                    List<Homework> demoHomeworks = homeworkMapper.selectByDemoId(demoId);
                    List<Integer> demoHomeworkIds = demoHomeworks.stream().map(Homework::getHomeworkId).collect(Collectors.toList());
                    System.out.println("该demo下所有作业id: " + demoHomeworkIds);
                    // 2.3 查询该学生在这些作业下的完成记录
                    List<HomeworkFinished> finishedList = homeworkFinishedService.selectByUserIdAndHomeworkIds(userId, demoHomeworkIds);
                    boolean allFinished = finishedList.size() == demoHomeworkIds.size() && finishedList.stream().allMatch(h -> h.getIsFinished() != null && h.getIsFinished() == 1);
                    // 2.4 如果全部完成，demonum+1
                    if (allFinished && sc.getDemoNum() < sc.getDemoUnlock()) {
                        sc.setDemoNum(sc.getDemoNum() + 1);
                        studentCourseService.update(sc);
                    }
                });
    }

    // 获取当前轮次号
    private int getCurrentRoundNumber(String userId, String homeworkId) {
        // 查询最大轮次号
        Integer maxRound = AiProgrammingConversationMapper.selectMaxRoundNumber(userId, homeworkId);

        // 如果还没有记录，从1开始；否则递增
        return (maxRound == null) ? 1 : maxRound + 1;
    }
}
